#include "asciiboard.h"
#include "rpi/keyboard.h"

/* assign tones to the qwerty layout, with 'a' being C3 and the first two
   rows of keys arranged like a piano keyboard.  The lower row isn't used
   for tones, instead other functions are assigned. */
const float keyboard_map[TONE_COUNT] = 
{
	261.63f, /* a = C4 */
	0.0f,    /* b = unused */
	0.0f,    /* c = unused */
	329.63f, /* d = E4 */
	311.13f, /* e = D#4 / Eb4*/
	349.23f, /* f = F4 */
	392.00f, /* g = G4 */
	440.00f, /* h = A4 (Concert A)  */
	0.0f,    /* i = unused */
	493.88f, /* j = B4 */
	523.25f, /* k   C5 */
	415.3f,  /* l = G#4 / Ab4 */
	0.0f, /* m = unused */
	466.16f, /* n = A#4 / Bb4 */
	493.88f, /* o = B4 */
	0.0f,    /* p = unused */
	0.0f,    /* q = unused */
	0.0f,    /* r = unused */
	293.66f, /* s = D4 */
	369.99f, /* t = F#4 / Gb4 */
	466.16f, /* u = A#4 / Bb4 */
	0.0f,    /* v = unused */
	277.18f, /* w = C#4 / Db4 */
	0.0f,    /* x = unused */
	415.3f,  /* y = G#4 / Ab4 */
	0.0f     /* z = unused */
};

int keyboard_synth(const char ch)
{
	float map[TONE_COUNT];
	const float *prev_map;
	static int mode = DEFAULT_MODE;
	int i;

	if (ch == RESET_CODE)
	{
		mode = DEFAULT_MODE;
		return NO_ERROR;
	}
	else if (ch == DEFAULT_MODE_CODE)
	{
		mode = DEFAULT_MODE;
		set_tone_map(default_tone_map, TONE_COUNT, CH_ONE);
		set_tone_map(default_tone_map, TONE_COUNT, CH_TWO);
		return NO_ERROR;
	}
	else if (ch == KEYBOARD_MODE_CODE)
	{
		mode = KEYBOARD_MODE;
		set_tone_map(keyboard_map, TONE_COUNT, CH_ONE);
		set_tone_map(keyboard_map, TONE_COUNT, CH_TWO);
		return NO_ERROR;
	}

	/* if the keyboard mode has been selected, process a few unique codes */
	if (mode == KEYBOARD_MODE)
	{
		if (ch == OCTAVE_UP_CODE)
		{
			/* channel 1 */
			prev_map = read_tone_map(CH_ONE);
			for (i = 0; i < TONE_COUNT; i++)
				map[i] = prev_map[i] * 2.0f;
			set_tone_map(map, TONE_COUNT, CH_ONE);
			/* channel 2 */
			prev_map = read_tone_map(CH_TWO);
			for (i = 0; i < TONE_COUNT; i++)
				map[i] = prev_map[i] * 2.0f;
			set_tone_map(map, TONE_COUNT, CH_TWO);
		}
		else if (ch == OCTAVE_DOWN_CODE)
		{
			prev_map = read_tone_map(CH_ONE);
			for (i = 0; i < TONE_COUNT; i++)
				map[i] = prev_map[i] * 0.5f;
			set_tone_map(map, TONE_COUNT, CH_ONE);
			prev_map = read_tone_map(CH_TWO);
			for (i = 0; i < TONE_COUNT; i++)
				map[i] = prev_map[i] * 0.5f;
			set_tone_map(map, TONE_COUNT, CH_ONE);
		}
	}
	/* ignore any other characters */

	return NO_ERROR;
}